package com.example.forum.services.impl;

import com.example.forum.common.AppResult;
import com.example.forum.common.ResultCode;
import com.example.forum.dao.MessageMapper;
import com.example.forum.exception.ApplicationException;
import com.example.forum.model.Message;
import com.example.forum.model.User;
import com.example.forum.services.IMessageService;
import com.example.forum.services.IUserService;
import com.example.forum.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class MessageServiceImpl implements IMessageService {

    @Resource
    private MessageMapper messageMapper;

    @Resource
    private IUserService userService;

    @Override
    public void create(Message message) {
        //校验参数
        if(message==null ||message.getPostUserId()<=0||message.getReceiveUserId()<=0|| StringUtil.isEmpty(message.getContent())){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 参数校验通过
        //校验当前用户是否存在
        User user=userService.selectById(message.getReceiveUserId());
        if(user==null||user.getDeleteState()==1){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //设置默认值
        //表示未读  默认状态
        message.setState((byte) 0);
        message.setCreateTime(new Date());
        message.setUpdateTime(new Date());
        message.setDeleteState((byte) 0);
        //添加到数据库
        int row = messageMapper.insertSelective(message);
        if(row!=1){
            log.warn(ResultCode.FAILED.toString()+", 受影响的行数!=1");
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
        log.info("站内信创建成功: 发送者ID={}, 接收者ID={}", message.getPostUserId(), message.getReceiveUserId());
    }

    @Override
    public int selectUnreadCount(Long receiveUserId) {
        //非空校验
        if(receiveUserId==null||receiveUserId<=0){
            log.warn("查询未读站内信数量参数校验失败: receiveUserId={}", receiveUserId);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用dao
        Integer count = messageMapper.selectUnreadCount(receiveUserId);
        //一般不会为null 如果为null 抛出异常
        if(count==null){
            log.warn(ResultCode.ERROR_SERVICES.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
        return count;
    }

    @Override
    public List<Message> selectByReceiveUserId(Long receiveUserId) {
        //非空校验
        if(receiveUserId==null||receiveUserId<=0){
            log.warn("查询用户站内信列表参数校验失败: receiveUserId={}", receiveUserId);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用dao
        List<Message> messages = messageMapper.selectByReceiveUserId(receiveUserId);
        return messages;
    }

    @Override
    public void updateStateById(Long id, Byte state) {
        //校验参数  0表示未读 1表示已读 2表示已回复
        if(id==null||id<=0||state<0||state>2){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //构建参数
        Message message=new Message();
        message.setId(id);
        message.setState(state);
        message.setUpdateTime(new Date());
        //执行dao
        int row=messageMapper.updateByPrimaryKeySelective(message);
        if(row!=1){
            log.warn(ResultCode.ERROR_SERVICES.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
        log.info("站内信状态更新成功: ID={}, 新状态={}", id, state);
    }

    @Override
    public Message selectById(Long id) {
        //非空校验
        if(id==null){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用dao 查询
        Message message = messageMapper.selectByPrimaryKey(id);
        return message;
    }

    @Override
    public void reply(Long repliedId, Message message) {
        //校验参数
        if(repliedId==null||repliedId<=0){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //校验回复站内信的状态
        Message existsMessage=messageMapper.selectByPrimaryKey(repliedId);
        if(existsMessage==null||existsMessage.getDeleteState()==1){
            log.warn(ResultCode.FAILED_Message_BANNED.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_Message_BANNED));
        }
        //将指定站内信id设置为已回复
       updateStateById(repliedId, (byte) 2);
        //调用dao
       create(message);
    }

    @Override
    public void markAllAsRead(Long userId) {
        // 参数校验
        if (userId == null || userId <= 0) {
            log.warn("标记全部已读参数校验失败: userId={}", userId);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        
        try {
            // 调用DAO方法批量更新状态
            int updatedCount = messageMapper.markAllAsRead(userId);
            log.info("用户ID={}的所有未读消息已标记为已读，更新了{}条消息", userId, updatedCount);
        } catch (Exception e) {
            log.error("标记全部已读异常: userId={}, 错误={}", userId, e.getMessage(), e);
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }

    @Override
    public void deleteMessage(Long id) {
        // 参数校验
        if (id == null || id <= 0) {
            log.warn("删除消息参数校验失败: id={}", id);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        
        try {
            // 逻辑删除，设置deleteState为1
            Message message = new Message();
            message.setId(id);
            message.setDeleteState((byte) 1);
            message.setUpdateTime(new Date());
            
            int row = messageMapper.updateByPrimaryKeySelective(message);
            if (row != 1) {
                log.warn("删除消息失败: id={}, 受影响行数={}", id, row);
                throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
            }
            
            log.info("消息删除成功: id={}", id);
        } catch (Exception e) {
            log.error("删除消息异常: id={}, 错误={}", id, e.getMessage(), e);
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }

    @Override
    public List<Message> selectByReceiveUserIdWithParams(Long receiveUserId, Message queryParam, int offset, int limit) {
        // 参数校验
        if (receiveUserId == null || receiveUserId <= 0) {
            log.warn("查询用户站内信列表参数校验失败: receiveUserId={}", receiveUserId);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        
        if (offset < 0 || limit <= 0) {
            log.warn("查询用户站内信列表分页参数校验失败: offset={}, limit={}", offset, limit);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        
        try {
            // 确保查询参数对象不为空
            if (queryParam == null) {
                queryParam = new Message();
                queryParam.setReceiveUserId(receiveUserId);
            }
            
            // 调用DAO方法，传递参数进行查询
            List<Message> messages = messageMapper.selectByReceiveUserIdWithParams(receiveUserId, queryParam, offset, limit);
            log.info("查询用户站内信成功: receiveUserId={}, 返回消息数量={}", receiveUserId, messages != null ? messages.size() : 0);
            
            return messages;
        } catch (Exception e) {
            log.error("查询用户站内信异常: receiveUserId={}, 错误={}", receiveUserId, e.getMessage(), e);
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }

    @Override
    public List<Message> selectByReceiveUserIdWithUserInfo(Long receiveUserId) {
        // 参数校验
        if (receiveUserId == null || receiveUserId <= 0) {
            log.warn("查询用户站内信列表(含用户信息)参数校验失败: receiveUserId={}", receiveUserId);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        
        try {
            // 调用DAO方法，查询带有用户信息的站内信列表
            List<Message> messages = messageMapper.selectByReceiveUserIdWithUserInfo(receiveUserId);
            log.info("查询用户站内信(含用户信息)成功: receiveUserId={}, 返回消息数量={}", 
                    receiveUserId, messages != null ? messages.size() : 0);
            
            return messages;
        } catch (Exception e) {
            log.error("查询用户站内信(含用户信息)异常: receiveUserId={}, 错误={}", receiveUserId, e.getMessage(), e);
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }

    @Override
    public java.util.Map<String, Integer> getCategoryCounts(Long receiveUserId) {
        // 参数校验
        if (receiveUserId == null || receiveUserId <= 0) {
            log.warn("获取消息分类计数参数校验失败: receiveUserId={}", receiveUserId);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        
        try {
            java.util.Map<String, Integer> result = new java.util.HashMap<>();
            
            // 获取所有消息总数
            int allCount = messageMapper.countMessagesByTypeAndStatus(receiveUserId, null, null);
            result.put("all", allCount);
            
            // 获取未读消息总数
            int unreadCount = messageMapper.countMessagesByTypeAndStatus(receiveUserId, null, (byte) 0);
            result.put("unread", unreadCount);
            
            // 获取私信消息总数
            int privateCount = messageMapper.countMessagesByTypeAndStatus(receiveUserId, "private", null);
            result.put("private", privateCount);
            
            // 获取系统通知总数
            int systemCount = messageMapper.countMessagesByTypeAndStatus(receiveUserId, "system", null);
            result.put("system", systemCount);
            
            // 获取评论回复总数
            int commentCount = messageMapper.countMessagesByTypeAndStatus(receiveUserId, "comment", null);
            result.put("comment", commentCount);
            
            // 获取点赞提醒总数
            int likeCount = messageMapper.countMessagesByTypeAndStatus(receiveUserId, "like", null);
            result.put("like", likeCount);
            
            log.info("获取消息分类计数成功: receiveUserId={}, counts={}", receiveUserId, result);
            return result;
        } catch (Exception e) {
            log.error("获取消息分类计数异常: receiveUserId={}, 错误={}", receiveUserId, e.getMessage(), e);
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }

    @Override
    public int markReadByType(Long userId, String type) {
        // 参数校验
        if (userId == null || userId <= 0) {
            log.warn("按类型标记已读参数校验失败: userId={}", userId);
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        
        // 如果类型为空，则设置为null以匹配所有类型
        if (type != null && type.trim().isEmpty()) {
            type = null;
        }
        
        try {
            // 调用DAO方法标记为已读
            int updatedCount = messageMapper.markReadByType(userId, type);
            log.info("用户ID={}的消息已按类型[{}]标记为已读，更新了{}条消息", userId, type, updatedCount);
            return updatedCount;
        } catch (Exception e) {
            log.error("按类型标记已读异常: userId={}, type={}, 错误={}", userId, type, e.getMessage(), e);
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }
}
